package com.study.kt._01grammar._02oop

fun main() {
    //可以直接使用单例类 访问类中属性与方法
    println(BlueManager.address)
    BlueManager.connection()

    //使用伴生对象
    //java中使用static声明字段或方法表示这些属于类不属于对象
    //kotlin使用伴生对象代替static
    println(BlueManager2.age) //也可以使用伴生对象的名称 BlueManager2.InnerClazz.age
    BlueManager2.showAge()
    val b = BlueManager2()
    //不在伴生类中，就需要对象访问
    println(b.name)
    b.showName()

    val b1 = BlueManager3.single
    val b2 = BlueManager3.single
    println(b1 == b2)
    b1.sayHello()
}

//对象声明，使用object修饰的本身就是对象，可以直接被调用
//定义单例 直接将class 关键字 改为object该类就是单例类
object BlueManager {
    var address = "100.100"
    var port = 100
    fun connection() {
        println("连接")
    }
}

//对于单例可以通过类直接访问，但是我们希望有些属性、方法需要通过对象访问就需要用到伴生对象
class BlueManager2 {
    //外界只能通过对象访问
    var name = "name is fauks"

    fun showName() {
        println("fauks")
    }

    // companion object 定义伴生对象 名称为InnerClazz 可以省略不写
    // InnerClazz为半生对象名字，可以省略默认为Companion
    // 虽然伴生对象看起来像类的静态成员，但在运行期，他们依旧是真是对象的实例成员(生成静态内部类)
    // 可以通过@JvmStatic 将成员生成为真正的静态
    companion object InnerClazz {
        //该对象中的属性、方法可以通过类访问
        var age = 11

        @JvmStatic
        fun showAge() {
            println("11")
        }
    }
}

//像Java一样定义单例(私有构造、对象、静态共有方法返回对象)
//private constructor() 将构造函数私有化
class BlueManager3 private constructor() {

    //使用伴生对象
    companion object {
        //使用val保证了类无法被修改
        //使用by lazy保证懒汉式+线程安全
        val single by lazy { BlueManager3() }
    }

    fun sayHello() {
        println("hello manager3")
    }
}